﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Ruandao.MiniAccess.OrMap;
using System.Data;
using System.Data.Common;
using System.Data.SQLite;

namespace Ruandao.MiniAccess.Sqlite {
  public  class SqliteAccessProvider : IAccessProvider{
        /// <summary>
        /// 数据库链接名称。
        /// </summary>
        string connectionString;
        bool isDebug = true;

		IDictionary<string, TableMap> tableMaps;

		/// <summary>
		/// 构造。
		/// 异常：OrMapException(无法定位到映射文件、映射文件格式错误)
		/// </summary>
		/// <remarks> 
		/// 获取实例时需要读取mdm.xml中的信息，mdm.xml文件根据实体所属的程序集
		/// 命名，存放的位置可以是实体所属的程序集或者应用程序所在目录，或者是
		/// 这两个目录的minidacmap子目录下。
		/// <br/>“SqlServer”提供者目前所支持的类型如下：
		/// <list type="bullet">
		/// <item><description>整数: tinyint、Smallint、int、bigint</description></item>
		/// <item><description>DateTime：datetime、smalldatetime、timestamp</description></item>
		/// <item><description>Guid：uniqueidentifier</description></item>
		/// <item><description>String: char、varchar、nchar、nvarchar、text、ntext</description></item>
		/// <item><description>byte[]: binary、varbinary、image</description></item>
		/// <item><description>Decimal: money、smallmoney</description></item>
		/// <item><description>float: float、real</description></item>
		/// <item><description>bool: bit</description></item>
		/// </list>
		/// </remarks>
		/// <param name="assembly">访问数据库的Access类所在的程序集。</param>
		/// <param name="providerName">在映射文件中指定的提供者的名字。</param>
		/// <param name="connectionName">配置文件中连接字符串的名字。</param>
		/// 获取某个Database对应的OR信息：TableMaps字典以及Database对象。
		/// 获取方式：
		/// 1）通过程序集，以及对应的xml文件。（目前的实现就是）
		/// 2）通过程序集，以及程序集的特性标记、实体类型的特性标记。
		/// 上述两种方式，都可以支持同一个程序集中使用多个数据库。
		public SqliteAccessProvider(Assembly assembly, string providerName, string connectionString)
		{
			OrMapFile orm = new OrMapFile(assembly, "System.Data.SQLite", providerName);
			this.connectionString = connectionString;
			this.isDebug = orm.IsDebug;
			tableMaps = OrMapHelper.GetTableMaps(orm.EntityNamespace, this.connectionString, orm.EntityTagList, this.isDebug);
		}
        /// <summary>
        /// 得到指定实体的OR映射数据。
        /// <br/>异常：OrMapException(指定实体的OR映射数据没有定义)。
        /// </summary>
        /// <param name="entityTypeFullName">实体的完全限定类名称。</param>
        /// <returns>实体和表的映射对象。</returns>
        TableMap GetTableMap(string entityTypeFullName) {
            if (tableMaps.Keys.Contains(entityTypeFullName))
                return tableMaps[entityTypeFullName];
            else
                throw new OrMapException("映射文件中没有定义实体" + entityTypeFullName + "的映射数据。");
        }

        #region IAccessProvider 成员


        public Database GetDatabase() {
			return new SqliteDatabase(connectionString);
        }

        public string ConnectionString {
			get { return this.connectionString; }
        }

        public string AccessType {
            get { return "System.Data.SQLite"; }
        }

        public int DeleteEntity<T>(params object[] keys) {
            throw new NotImplementedException();
        }

        public int DeleteEntities<T>(string conditions) {
            throw new NotImplementedException();
        }

        public int InsertEntity<T>(T t) where T : IEntity, new() {
            throw new NotImplementedException();
        }

        public int UpdateEntity<T>(T t, params object[] keys) where T : IEntity, new() {
            throw new NotImplementedException();
        }

        public IList<T> SearchEntities<T>(string condition) where T : IEntity, new() {
			Type entityType = typeof(T);
			TableMap tableMap = GetTableMap(entityType.FullName);

			IList<T> entities = new List<T>();

			using (IDataReader reader = GetExecuteReader(tableMap.SearchCommand, condition))
			{

				while (reader.Read())
				{
					T t = new T();
					//LoadFromReader(t, reader);
					entities.Add(t);
				}
			}
			return entities;
        }

        public T FetechEntity<T>(params object[] keys) where T : IEntity, new() {
            throw new NotImplementedException();
        }
		/// <summary>
		/// 执行SQL语句，返回IDataReader的一个实现类实例
		/// </summary>
		/// <param name="sql"></param>
		/// <param name="parameterValues"></param>
		/// <returns></returns>
		private IDataReader GetExecuteReader(string sql, params object[] parameterValues)
		{
			List<String> tableNames = new List<String>();
			SQLiteConnection conn = OrMapHelper.getConn(this.ConnectionString);
			SQLiteCommand cmd = new SQLiteCommand(conn);
			conn.Open();
			cmd.CommandText = sql;
			SQLiteDataReader dr = cmd.ExecuteReader();
			return dr;
		}

        public T FindEntity<T>(string condition) where T : IEntity, new() {
			TableMap tableMap = GetTableMap(typeof(T).FullName);
			using (IDataReader reader = GetExecuteReader(tableMap.SearchCommand, condition))
			{
				while (reader.Read())
				{
					T t = new T();
					//LoadFromReader(t, reader);
					return t;
				}
			}
			return default(T);
        }

        public void LoadFromReader<T>(T t, System.Data.IDataReader reader) where T : IEntity, new() {
			throw new NotImplementedException();
        }

        public string[] GetKeyPropertyNames<T>() where T : IEntity, new() {
            throw new NotImplementedException();
        }

        public int ExecuteNonQuery(string commandText, params System.Data.Common.DbParameter[] parameters) {
            throw new NotImplementedException();
        }

        public object ExecuteScalar(string commandText, params System.Data.Common.DbParameter[] parameters) {
            throw new NotImplementedException();
        }

        public System.Data.IDataReader ExecuteReader(string commandText, params System.Data.Common.DbParameter[] parameters) {
            throw new NotImplementedException();
        }

        public object ExecuteScalar(string storedProcedureName, params object[] parameterValues) {
            throw new NotImplementedException();
        }

        public System.Data.IDataReader ExecuteReader(string storedProcedureName, params object[] parameterValues) {
            throw new NotImplementedException();
        }

        public int ExecuteNonQuery(string storedProcedureName, params object[] parameterValues) {
            throw new NotImplementedException();
        }
        #endregion
    }
}
